package com.suket.jnn;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class NetworkFactory {

  static Logger logger = Logger.getLogger(NetworkFactory.class);

  public static Network createNetwork( int totInputLayer ,
      int[] arrHiddenLayer , int totOutputLayer ) {
    Network network = null;
    if ( totInputLayer < 1 ) {
      logger.log(Level.WARN, "Failed to create network "
          + ", found zero total input layer");
      return network;
    }
    if ( totOutputLayer < 1 ) {
      logger.log(Level.WARN, "Failed to create network "
          + ", found zero total output layer");
      return network;
    }
    if ( arrHiddenLayer == null ) {
      logger.log(Level.WARN, "Failed to create network "
          + ", found null array hidden layer");
      return network;
    }
    if ( !verifyHiddenLayer(arrHiddenLayer) ) {
      logger.log(Level.WARN, "Failed to create network "
          + ", failed to verify array hidden layer");
    }

    // create random object
    Random random = new Random();

    // create input layer
    Layer inputLayer = LayerFactory.createLayer(null, "ilyr", totInputLayer,
        random);

    // create hidden layer
    List hiddenLayers = new ArrayList();
    Layer previousLayer = inputLayer;
    for ( int i = 0 ; i < arrHiddenLayer.length ; i++ ) {
      Layer hiddenLayer = LayerFactory.createLayer(previousLayer, "hlyr-" + i,
          arrHiddenLayer[i], random);
      hiddenLayers.add(hiddenLayer);
      previousLayer = hiddenLayer;
    }

    // create output layer
    Layer outputLayer = LayerFactory.createLayer(previousLayer, "olyr",
        totOutputLayer, random);

    // compose ilayer , hlayer and olayer into network
    network = new Network();
    network.setInputLayer(inputLayer);
    network.setHiddenLayers(hiddenLayers);
    network.setOutputLayer(outputLayer);

    return network;
  }

  private static boolean verifyHiddenLayer( int[] arrHiddenLayer ) {
    boolean verify = true;
    for ( int i = 0 ; i < arrHiddenLayer.length ; i++ ) {
      if ( arrHiddenLayer[i] < 1 ) {
        verify = false;
        logger.log(Level.WARN, "Failed to verify hidden layer "
            + ", found zero nodes in layer #" + i);
        return verify;
      }
    }
    return verify;
  }

}
